package cn.lg.soar.common.util.jackson.deserializer;

import cn.lg.soar.common.data.dict.IDict;
import cn.lg.soar.common.util.EnumUtils;
import cn.lg.soar.common.util.reflect.ReflectUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

import java.io.IOException;
import java.lang.reflect.Field;

/**
 * IDict 反序列化
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class EnumDeserializer extends JsonDeserializer<Enum> implements ContextualDeserializer {

    public static final EnumDeserializer instance = new EnumDeserializer();

    private EnumDeserializer(){}

    @Override
    public Enum deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException, JsonProcessingException {
        Object currentValue = jsonParser.getCurrentValue();
        Field field = ReflectUtil.getField(currentValue.getClass(), jsonParser.currentName());
        Class<?> enumType = field.getType();
        if (IDict.class.isAssignableFrom(enumType)) {
            return (Enum) EnumUtils.valueOf((Class<? extends IDict<?>>) enumType, jsonParser.getText());
        }
        return Enum.valueOf((Class<? extends Enum>)enumType, jsonParser.getText());
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctx, BeanProperty property) {
        if (property != null) {
            JavaType type = property.getType();
            Class<?> rawClass = type.getRawClass();
            if (rawClass.isEnum()) {
                if (IDict.class.isAssignableFrom(rawClass)) {
                    return new IDictInnerDeserializer(rawClass);
                }
                return new EnumInnerDeserializer(rawClass);
            }
        }
        return this;
    }

    class EnumInnerDeserializer extends JsonDeserializer<Enum<?>> {

        private  final Class<? extends Enum> enumType;

        EnumInnerDeserializer(Class<?> enumType) {
            this.enumType = (Class<? extends Enum>) enumType;
        }

        @Override
        public Enum<?> deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException, JsonProcessingException {
            return (Enum<?>) Enum.valueOf(enumType, jsonParser.getText());
        }

    }

    class IDictInnerDeserializer extends JsonDeserializer<IDict<?>> {

        private  final Class<? extends IDict<?>> enumType;

        IDictInnerDeserializer(Class<?> enumType) {
            this.enumType = (Class<? extends IDict<?>>) enumType;
        }

        @Override
        public IDict<?> deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException, JsonProcessingException {
            return EnumUtils.valueOf(enumType, jsonParser.getText());
        }

    }

}
